#include "ImpSphereObject.h"
#include <math.h>
#include <algorithm>
#include <iostream>
#include "Vector3.h"

using namespace std;

ImpSphereObject::ImpSphereObject(float r) : _radius(r) {
    InitObject("ImpSphereObject");
}

bool ImpSphereObject::Intersects(Ray trace_ray, Vector3 &location)
{
    float a = Vector3::dot(trace_ray.direction, trace_ray.direction);
    float b = 2 * Vector3::dot(trace_ray.start - _position, trace_ray.direction);
    float c = Vector3::dot(trace_ray.start - _position, trace_ray.start - _position) - _radius * _radius;
    float square = sqrt(b*b - c*4*a);
    float t1 = -(b + square) / (2 * a);
    float t2 = -(b - square) / (2 * a);



    if (t1 == t1 && t1 > 0.0 && t2 > 0.0)
    {
        location =  trace_ray.direction * std::min(t1, t2) + trace_ray.start;
        return true;
    }

    return false;
}


Vector3 ImpSphereObject::GetRandomPositionInObject()
{
    float random = rand();
    random /= RAND_MAX;
    return _position + _radius*random*Vector3::GetRandomNormalizedKernel();
}

Ray ImpSphereObject::Refract(Ray trace_ray, Vector3 location, float refractiveIndex)
{
    float n1 = trace_ray._RefractiveIndex;
    float n2 = refractiveIndex;

    Vector3 Normal = GetNormal(location);

    if (Vector3::dot(Normal, trace_ray.direction) > 0.0f)
        Normal = -1.0 * Normal;

    float cost1 = Vector3::dot(Normal, -1.0f * trace_ray.direction);
    float cost2 = sqrt(1.0 - pow(n1/n2, 2.0f)*(1.0 - cost1*cost1));

    if (cost1 < 0.0)
        cost2 *= -1.0;

    Vector3 refract = 1.0 * Vector3::normalize(((n1/n2) * trace_ray.direction) + ((n1/n2)*cost1 - cost2) * Normal);

    Ray refractedRay(refract, location, trace_ray.life);
    refractedRay._RefractiveIndex = refractiveIndex;

    return refractedRay;
}

Vector3 ImpSphereObject::GetNormal(Vector3 location)
{
    return Vector3::normalize(location-GetPosition());
}


float ImpSphereObject::DistanceToPointPow2(Vector3 p)
{
    Vector3 dist = GetPosition() - p;
    return Vector3::dot(dist, dist) - _radius;
}
